home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / xvisrc.zip / MSDOS_C.C < prev    next >
C/C++ Source or Header  |  1992-07-28  |  10KB  |  541 lines

  1. /* Copyright (c) 1990,1991,1992 Chris and John Downey */
  2. #ifndef lint
  3. static char *sccsid = "@(#)msdos_c.c    2.1 (Chris & John Downey) 7/29/92";
  4. #endif
  5.  
  6. /***
  7.  
  8. * program name:
  9.     xvi
  10. * function:
  11.     PD version of UNIX "vi" editor, with extensions.
  12. * module name:
  13.     msdos_c.c
  14. * module function:
  15.     System interface routines for MS-DOS.
  16.  
  17.     The system interface consists of this module & msdos_a.asm;
  18.     the terminal interface for IBM PC compatibles consists of
  19.     ibmpc_a.asm & ibmpc_c.c. Some comments on the demarcation
  20.     between system interface and terminal interface modules are in
  21.     the source.ms document.
  22. * history:
  23.     STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  24.     Originally by Tim Thompson (twitch!tjt)
  25.     Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  26.     Heavily modified by Chris & John Downey
  27.  
  28. ***/
  29.  
  30. #include "xvi.h"
  31.  
  32. #ifdef __ZTC__
  33.     /*
  34.      * Zortech 3.0 has a really stupid method of specifying
  35.      * filename expansion on the command line.
  36.      */
  37. #   ifdef WILDCARDS
  38.     WILDCARDS
  39. #   endif /* WILDCARDS */
  40.  
  41.     /*
  42.      * Set default stack size. This seems a reasonable compromise.
  43.      */
  44.     unsigned _stack = 20480;
  45. #endif        /* __ZTC__ */
  46.  
  47. void
  48. ignore_signals(void)
  49. {
  50.     msdsignal(&kbdintr);
  51. }
  52.  
  53. void
  54. sys_init(void)
  55. {
  56.     char    *sh;
  57.  
  58.     /*
  59.      * Set up a default value for Ps(P_shell). This can be overridden
  60.      * by xvi_startup() (in startup.c) if %SHELL% is defined, or if a
  61.      * value is given explicitly in the startup
  62.      * script.
  63.      *
  64.      * %COMSPEC% should always be defined on MS-DOS. The system can't
  65.      * really run without it.
  66.      */
  67.     if ((sh = getenv("COMSPEC")) != NULL) {
  68.     set_param(P_shell, sh);
  69.     }
  70.     tty_open(&Rows, &Columns);
  71.     sys_startv();
  72. }
  73.  
  74. static    enum {
  75.     m_SYS = 0,
  76.     m_VI
  77. }    curmode;
  78.  
  79. /*
  80.  * Set up video state for editor.
  81.  */
  82. void
  83. sys_startv(void)
  84. {
  85.     if (curmode == m_SYS) {
  86.     tty_startv();
  87.     set_colour(Pn(P_colour));
  88.     curmode = m_VI;
  89.     }
  90. }
  91.  
  92. /*
  93.  * Restore video state to what it was when we started.
  94.  */
  95. void
  96. sys_endv(void)
  97. {
  98.     if (curmode == m_VI) {
  99.     tty_goto(Rows - 1, 0);
  100.     set_colour(Pn(P_systemcolour));
  101.     erase_line();
  102.     tty_endv();
  103.     /*
  104.      * tty_endv() is responsible for calling
  105.      * flush_output().
  106.      */
  107.     curmode = m_SYS;
  108.     }
  109. }
  110.  
  111. void
  112. sys_exit(int r)
  113. {
  114.     sys_endv();
  115.     tty_close();
  116.     exit(r);
  117. }
  118.  
  119. #ifndef W_OK
  120. #    define    F_OK    0
  121. #    define    W_OK    2
  122. #endif
  123.  
  124. /*
  125.  * Returns TRUE if file does not exist or exists and is writeable.
  126.  */
  127. bool_t
  128. can_write(char* file)
  129. {
  130. #ifdef __ZTC__
  131.     struct FIND    *p;
  132.  
  133.     p = findfirst(file, FA_HIDDEN | FA_SYSTEM | FA_DIREC);
  134.  
  135.     return(p == NULL ||
  136.        (p->attribute & (FA_RDONLY | FA_HIDDEN | FA_SYSTEM | FA_DIREC)) == 0);
  137. #else    /* __ZTC__ */
  138.     return access(file, F_OK) != 0 || access(file, W_OK) == 0;
  139. #endif    /* __ZTC__ */
  140. }
  141.  
  142. #ifndef __ZTC__
  143.  
  144. /*
  145.  * The Zortech library has this anyway.
  146.  */
  147. void
  148. sleep(n)
  149. unsigned    n;
  150. {
  151.     /*
  152.      * This works with Microsoft C.
  153.      */
  154.     time_t    start = time((time_t*) 0);
  155.  
  156.     flush_output();
  157.     while (time((time_t*) 0) < start + n)
  158.     ;
  159. }
  160.  
  161. #endif /* not __ZTC__ */
  162.  
  163. void
  164. delay()
  165. {
  166.     clock_t start = clock();
  167.  
  168.     flush_output();
  169.     while (clock() < start + CLK_TCK / 5)
  170.     ;
  171. }
  172.  
  173. /*
  174.  * This function is only used by tempfname(). It constructs a filename
  175.  * suffix based on an index number.
  176.  *
  177.  * The suffix ".$$$" is commonly used for temporary file names on
  178.  * MS-DOS & OS/2 systems. We also use the sequence ".$$1", ".$$2" ...
  179.  * ".fff" (all digits are hexadecimal).
  180.  */
  181. static char * near
  182. hexsuffix(i)
  183. unsigned    i;
  184. {
  185.     static char    suffix [] = ".$$$";
  186.     static char    hextab [] = "0123456789abcdef";
  187.     char*        sp = &suffix[3];
  188.  
  189.     while (sp > suffix) {
  190.     if (i > 0) {
  191.         *sp-- = hextab [i & 0xf];
  192.         i >>= 4;
  193.     } else {
  194.         *sp-- = '$';
  195.     }
  196.     }
  197.     return suffix;
  198. }
  199.  
  200. /*
  201.  * Construct unique name for temporary file, to be used as a backup
  202.  * file for the named file.
  203.  */
  204. char*
  205. tempfname(srcname)
  206. char        *srcname;
  207. {
  208.     char    *srctail,
  209.         *srcdot,
  210.         *endp,
  211.         *retp;
  212.     unsigned    indexnum = 0;
  213.     unsigned    baselen;
  214.  
  215.     srctail = srcdot = NULL;
  216.     endp = srcname;
  217.  
  218.     while (*endp) {
  219.     switch (*endp++) {
  220.     case '\\':
  221.     case '/':
  222.         srctail = endp;
  223.         srcdot = (char*) 0;
  224.         continue;
  225.     case '.':
  226.         srcdot = endp - 1;
  227.     }
  228.     }
  229.  
  230.     if (srctail == NULL) {
  231.     /*
  232.      * We haven't found any directory separators ('/' or '\\').
  233.      */
  234.     srctail = srcname;
  235.     /*
  236.      * Check to see if there's a disk drive name. If there
  237.      * is, skip over it.
  238.      */
  239.     if (*srcname && is_alpha(*srcname) && srcname[1] == ':') {
  240.         srctail = &srcname[2];
  241.     }
  242.     }
  243.  
  244.     /*
  245.      * There isn't a dot in the trailing part of the filename:
  246.      * just add it at the end.
  247.      */
  248.     if (srcdot == NULL) {
  249.     srcdot = endp;
  250.     }
  251.  
  252.     /*
  253.      * Don't make name too long.
  254.      */
  255.     if (srcdot - srctail > MAXNAMLEN - 4)
  256.     srcdot = srctail + MAXNAMLEN - 4;
  257.     if (srcdot - srcname > MAXPATHLEN - 4)
  258.     srcdot = srcname + MAXPATHLEN - 4;
  259.     baselen = srcdot - srcname;
  260.     /*
  261.      * Allocate space for new temporary file name ...
  262.      */
  263.     if ((retp = alloc(baselen + 5)) == NULL)
  264.     return NULL;
  265.     if (baselen > 0)
  266.     (void) memcpy(retp, srcname, baselen);
  267.     do {
  268.     /*
  269.      * Keep trying this until we get a unique file name.
  270.      */
  271.     strcpy(&retp[baselen], hexsuffix(indexnum++));
  272.     } while (exists(retp));
  273.     return retp;
  274. }
  275.  
  276. /*
  277.  * Fake out a pipe by writing output to temp file, running a process with
  278.  * i/o redirected from this file to another temp file, and then reading
  279.  * the second temp file back in.
  280.  */
  281. bool_t
  282. sys_pipe(cmd, writefunc, readfunc)
  283. char    *cmd;
  284. int    (*writefunc) P((FILE *));
  285. long    (*readfunc) P((FILE *));
  286. {
  287.     char    *temp1;
  288.     FILE    *fp;
  289.     bool_t    retval;
  290.  
  291.     /*
  292.      * Create first temporary file ...
  293.      */
  294.     if ((temp1 = tempfname("xvi_out")) == NULL ||
  295.                     (fp = fopen(temp1, "w")) == NULL) {
  296.     retval = FALSE;
  297.     } else {
  298.     char    *temp2 = NULL;
  299.     int    savcon;
  300.     int    fd1 = -1,
  301.         fd2 = -1;
  302.  
  303.     /*
  304.      * ... then write to it & close it ...
  305.      */
  306.     (void) (*writefunc)(fp);
  307.     (void) fclose(fp);
  308.  
  309.     /*
  310.      * ... then re-open it for reading, open second one
  311.      * for writing & re-arrange file descriptors.
  312.      *
  313.      * Note that we assume that the editor's standard
  314.      * input, output & error files are the same device,
  315.      * since I can't imagine how any of them could
  316.      * usefully be redirected to anything else.
  317.      */
  318.  
  319. #ifndef O_BINARY
  320. #    define O_BINARY 0
  321. #endif
  322. #ifndef O_EXCL
  323. #    define O_EXCL 0
  324. #endif
  325.     if (
  326.         (savcon = dup(0)) < 3
  327.         ||
  328.         (fd1 = open(temp1, O_RDONLY | O_BINARY)) < 3
  329.         ||
  330.         (temp2 = tempfname("xvi_in")) == NULL 
  331.         ||
  332.         (fd2 = open(temp2, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0600)) < 3
  333.     ) {
  334.         retval = FALSE;
  335.     } else {
  336.         (void) dup2(fd1, 0);
  337.         (void) dup2(fd2, 1);
  338.         (void) dup2(fd2, 2);
  339.  
  340.         (void) close(fd1);
  341.         (void) close(fd2);
  342.         fd1 = fd2 = -1;
  343.  
  344.         /*
  345.          * Run the command.
  346.          */
  347.         (void) system(cmd);
  348.  
  349.         /*
  350.          * Restore our standard input, output & error
  351.          * files.
  352.          */
  353.         (void) dup2(savcon, 0);
  354.         (void) dup2(savcon, 1);
  355.         (void) dup2(savcon, 2);
  356.  
  357.         /*
  358.          * Now read from the second temporary file,
  359.          * close it, & we're done.
  360.          */
  361.         if ((fp = fopen(temp2, "r")) == NULL) {
  362.         retval = FALSE;
  363.         } else {
  364.         (void) (*readfunc)(fp);
  365.         (void) fclose(fp);
  366.         retval = TRUE;
  367.         }
  368.     }
  369.     /*
  370.      * Clean up.
  371.      */
  372.     if (temp2) {
  373.         (void) remove(temp2);
  374.         free(temp2);
  375.     }
  376.     if (savcon > 2)
  377.         (void) close(savcon);
  378.     if (fd1 > 2)
  379.         (void) close(fd1);
  380.     if (fd2 > 2)
  381.         (void) close(fd2);
  382.     }
  383.  
  384.     if (temp1) {
  385.     (void) remove(temp1);
  386.     free(temp1);
  387.     }
  388.  
  389.     return(retval);
  390. }
  391.  
  392. #if 0
  393.  
  394. /*
  395.  * The following functions are untested because neither of us has
  396.  * access to an MS-DOS compiler at the moment.
  397.  */
  398.  
  399. /*
  400.  * Expand environment variables in filename.
  401.  */
  402.  
  403. #define VMETACHAR    '$'
  404.  
  405. static char * near
  406. vexpand(name)
  407.     char        *name;
  408. {
  409.     static Flexbuf    b;
  410.     register char    *p1, *p2;
  411.  
  412.     if ((p2 = strchr(name, VMETACHAR)) == (char *) NULL) {
  413.     return name;
  414.     }
  415.     flexclear(&b);
  416.     p1 = name;
  417.     while (*p1) {
  418.     register int    c;
  419.     register char    *val;
  420.     Flexbuf        vname;
  421.  
  422.     while (p1 < p2) {
  423.         (void) flexaddch(&b, *p1++);
  424.     }
  425.     flexnew(&vname);
  426.     for (p2++; (c = *p2) != '\0' && (is_alnum(c) || c == '_'); p2++) {
  427.         (void